package grafos;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;



public abstract class AbstractGraph<V> {
	protected VertexNode<V> g;  //referencia al grafo
	
	public AbstractGraph(){
		g=null;
	}
	
	public boolean addVert(V vertex){
		VertexNode<V> aux=g;
		while((aux!=null)&&(aux.vertex!= vertex)) aux=aux.nextVert;
		if(aux!=null) return false; //Ya existe
		else{
			aux= new VertexNode<V>(vertex);
			aux.nextVert=g;
			g=aux;
			return true;
		}
	}
	
	public boolean removeVert(V vertex){
		VertexNode<V> aux=g;
		VertexNode<V> prevAux=null;
		while((aux!=null)&&(aux.vertex!= vertex)){
			prevAux=aux;
			aux=aux.nextVert;
		}
		if(aux==null) return false; //No existe
		else{
			removeIncomingEdges(aux);
			if(prevAux==null) g=g.nextVert; //era el primer nodo, lo borramos;
			else prevAux.nextVert=aux.nextVert; //mas de un nodo
			return true;
		}
	}
	
	public boolean isVert(V vertex){
		VertexNode<V> aux=g;
		while((aux!=null)&&(aux.vertex!= vertex)) aux=aux.nextVert;
		return aux!=null; //si existe
	}
	
	public boolean isEmpty(){
		return g==null;
	}
	
	public Set<V> getIncomingVertexOf(V vertex){
		VertexNode<V> vertexNodeAux = getVertexNode(vertex);
		@SuppressWarnings("rawtypes")
		AdjNode adjNodeAux = vertexNodeAux.adj;
		Set<V> set=null;
		if(adjNodeAux!=null) set=new HashSet<V>();
		while(adjNodeAux!=null){
			@SuppressWarnings("unchecked")
			VertexNode<V> a = adjNodeAux.dest;
			set.add(a.vertex);
			adjNodeAux=adjNodeAux.nextAdj;
		}
		return set;
	}
	
	private VertexNode<V> getVertexNode(V vertex){
		VertexNode<V> aux=g;
		while((aux!=null)&&(aux.vertex!= vertex)) aux=aux.nextVert;
		return aux; //Ya existe
	}
	
	private void removeIncomingEdges(VertexNode<V> vertex){
		VertexNode<V> aux=g;
		while(aux!=null){
			removeEdge(aux,vertex);
			aux=aux.nextVert;
		}
	}
	
	@SuppressWarnings("unchecked")
	private void removeEdge(VertexNode<V> org,VertexNode<V> vertex){
		@SuppressWarnings("rawtypes")
		AdjNode aux=org.adj;
		@SuppressWarnings("rawtypes")
		AdjNode prevAux=null;
		while((aux!=null)&&(aux.dest!=vertex)){
			prevAux=aux;
			aux=aux.nextAdj;
		}
		if(aux!=null){
			if(prevAux==null) org.adj=null;
			else prevAux.nextAdj=aux.nextAdj;
		}
	}
	
	public abstract boolean removeEdge(V vertexOrg,V vertexDst);
	public abstract boolean isEdge(V vertexOrg,V vertexDst);
	public abstract boolean addEdge(V vertexOrg,V vertexDst);
}
